<template>
  <div class="editor-border-wrap">
    <div :class="['wang-editor-container relative mx-auto', {
      scrollable: props.scrollable,
      'fixed-height': !!props.height,
      'enable-video': props.enableVideo
    }]" :style="containerStyle">
      <!-- 工具栏 -->
      <Toolbar :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" />
      <!-- 编辑器内容区 -->
      <Editor v-model="valueHtml" :defaultConfig="editorConfig" :mode="mode" :maxLength="props.maxLength"
        @onCreated="handleCreated" @onChange="handleChange" @onFocus="handleFocus" @onBlur="handleBlur" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { shallowRef, ref, onBeforeUnmount, onMounted, watch, computed } from 'vue';
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
import type { IDomEditor, IEditorConfig, IToolbarConfig } from '@wangeditor/editor';
import { i18nChangeLanguage } from '@wangeditor/editor'
import { cleanWangEditorContent, prepareWangEditorContent } from '#/utils/editorUtils'
import { safeSetEditorContent, handleEditorError, handleSlateError, isSlateError } from '#/utils/editorErrorHandler'
import { obsUpload, obsDownload } from '#/utils/obs'
import { convertKeysToObsUrls } from '#/utils/getImgUrl'
import { ElMessage } from 'element-plus'
import { $t } from '@vben/locales'

defineOptions({ name: 'WangEditor' })
const emits = defineEmits(['update:modelValue', 'init']);
const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  disabled: {
    type: Boolean,
    default: false
  },
  mode: {
    type: String,
    default: 'simple' // 'default' 或 'simple'
  },
  // 固定高度（可选，支持 number 或 string，如 400 或 'calc(100vh - 200px)'）
  height: {
    type: [Number, String] as any,
    default: undefined
  },
  // 最小高度（未传入 height 时生效）
  minHeight: {
    type: [Number, String] as any,
    default: 350
  },
  // 是否允许内部滚动
  scrollable: {
    type: Boolean,
    default: true
  },
  // 自定义占位文案
  placeholder: {
    type: String,
    default: ''
  },
  // 最大内容长度限制
  maxLength: {
    type: Number,
    default: 0 // 0表示不限制
  },
  // 是否启用视频功能
  enableVideo: {
    type: Boolean,
    default: false
  },
  // 是否启用图片功能
  enableImage: {
    type: Boolean,
    default: true
  }
});

// 工具栏配置（TypeScript 类型约束）- 明确定义工具栏按钮，根据props控制视频功能
const toolbarConfig = computed<IToolbarConfig | any>(() => {
  // 定义基础工具栏按钮
  const defaultToolbarKeys = [
    'headerSelect',
    'blockquote',
    '|',
    'bold',
    'underline',
    'italic',
    // 自定义分组
    {
      key: 'group-more-style1',
      iconSvg: '<svg viewBox="0 0 1024 1024"><path d="M204.8 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M505.6 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M806.4 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path></svg>', // 三个点的图标SVG代码，可按需更换
      menuKeys: ['through', 'code', 'sub', 'sup', 'clearStyle']
    },
    'color',
    'bgColor',
    '|',
    'fontSize',
    'fontFamily',
    'lineHeight',
    '|',
    // 'bulletedList',
    // 'numberedList',
    // 'insertTable',
    // 自定义分组
    {
      key: 'group-more-style2',
      iconSvg: '<svg viewBox="0 0 1024 1024"><path d="M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z"></path></svg>', // 三个点的图标SVG代码，可按需更换
      menuKeys: ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyJustify']
    },
    // 自定义分组
    {
      key: 'group-more-style3',
      iconSvg: '<svg viewBox="0 0 1024 1024"><path d="M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z"></path></svg>', // 三个点的图标SVG代码，可按需更换
      menuKeys: ['indent', 'delIndent']
    },
    'emotion',
    // 'insertLink',
    'divider',
    '|',
    'undo',
    'redo'
  ];

  // 复制基础按钮列表
  const keys = [...defaultToolbarKeys];

  // 在emotion后面添加图片上传按钮
  const emotionIndex = keys.indexOf('emotion');
  const insertPosition = emotionIndex >= 0 ? emotionIndex + 1 : keys.length - 3; // 在undo前面
  // 根据enableVideo属性决定是否添加视频上传按钮
  if (props.enableVideo) {
    keys.splice(insertPosition, 0, 'uploadVideo');
  }
  if (props.enableImage) {
    // 决定是否添加图片上传按钮
    keys.splice(insertPosition, 0, 'uploadImage');
  }

  return {
    toolbarKeys: keys
  };
});
// 计算容器样式，支持固定高度/最小高度与内部滚动
const containerStyle = computed(() => {
  if (!props.height) return props.minHeight ? { minHeight: `${props.minHeight}px` } : {};
  else
    return {
      height: typeof props.height === 'number' ? `${props.height}px` : props.height
    };
});
// 编辑器实例引用（必须使用 shallowRef）
const editorRef = shallowRef<IDomEditor | null>(null);
// 编辑器内容 HTML，确保是字符串类型
const valueHtml = ref(String(props.modelValue || ''))
// 状态提示
const showStatus = ref(false);
// 模式（默认模式或简洁模式）
const mode = ref<'default' | 'simple'>(props.mode as 'default' | 'simple');
// 编辑器配置（TypeScript 类型约束）
const editorConfig: IEditorConfig | any = {
  modalAppendToBody: true, // 设置modalAppendToBody为true
  // 如果有自定义placeholder则优先，否则使用默认
  placeholder: props.placeholder || $t('common.inputPhTxt', [$t('common.contentTxt')]),
  // 最大内容长度限制
  maxLength: props.maxLength > 0 ? props.maxLength : undefined,
  MENU_CONF: {
    // 配置图片上传功能 - 完全参考 edit-template-dialog.vue 中的实现
    uploadImage: {
      // 自定义上传图片
      customUpload(file: File, insertFn: Function) {
        // console.log('WangEditor 开始上传图片:', file.name, '大小:', file.size, '类型:', file.type);

        // 完全复制 edit-template-dialog.vue 中的文件验证逻辑 (line 50-64)
        const allowedTypes = ['image/bmp', 'image/png', 'image/jpeg', 'image/jpg'];
        const isValidType = allowedTypes.includes(file.type);
        const isLt5M = file.size / 1024 / 1024 < 5;

        if (!isValidType) {
          ElMessage.error($t('common.imageFormatTxt'));
          return;
        }
        if (!isLt5M) {
          ElMessage.error($t('common.imageSizeLimitTxt', ['5']));
          return;
        }

        // 显示上传中提示
        ElMessage.info($t('questionBank.uploading'));

        // 上传图片到OBS
        obsUpload({
          Key: file.name,
          SourceFile: file
        }, (err: any, result: any, key: string) => {
          if (err) {
            // console.error('WangEditor 图片上传失败:', err);
            ElMessage.error($t('common.uploadFailTxt'));
            return;
          }

          // console.log('WangEditor 图片上传成功，Key:', key);
          // console.log('WangEditor 上传结果:', result);

          // 获取临时URL用于预览和显示
          obsDownload({
            Key: key,
            SaveByType: 'file'
          }, (downloadErr: any, downloadResult: any) => {
            if (downloadErr) {
              // console.error('WangEditor 获取图片URL失败:', downloadErr);
              ElMessage.error($t('common.operationFailedTxt'));
              return;
            }

            try {
              // 获取 SignedUrl 用于预览和显示
              const imageUrl = downloadResult?.InterfaceResult?.Content?.SignedUrl || downloadResult?.InterfaceResult?.Content;
              // console.log('WangEditor 获取到的图片URL:', imageUrl);
              // console.log('WangEditor 完整下载结果:', downloadResult);

              if (imageUrl) {
                // 使用 setTimeout 避免 Vue 响应式冲突
                setTimeout(() => {
                  try {
                    // 插入图片，使用实际URL作为src以便正常显示，同时使用alt属性保存key值用于保存时识别
                    const imgHtml = `<img src="${imageUrl}" alt="${key || $t('common.uploadedImageTxt')}" style="max-width: 100%;">`;
                    // console.log('WangEditor 准备插入的HTML:', imgHtml);

                    // 直接插入HTML而不是使用insertFn，因为我们需要自定义img标签
                    const editor = editorRef.value;
                    if (editor) {
                      editor.dangerouslyInsertHtml(imgHtml);
                      ElMessage.success($t('common.uploadSuccessTxt'));
                      // console.log('WangEditor 图片插入成功');
                    } else {
                      ElMessage.error($t('common.operationFailedTxt'));
                      // console.error('WangEditor 编辑器未初始化');
                    }
                  } catch (insertError) {
                    // console.error('WangEditor 插入图片失败:', insertError);
                    ElMessage.error($t('common.operationFailedTxt'));
                  }
                }, 50);
              } else {
                // console.error('WangEditor 未能获取有效的图片URL');
                // console.error('WangEditor 下载结果详情:', downloadResult);
                ElMessage.error($t('common.operationFailedTxt'));
              }
            } catch (error) {
              // console.error('WangEditor 处理图片URL失败:', error);
              ElMessage.error($t('common.operationFailedTxt'));
            }
          });
        });
      },

      // 限制文件大小 5MB
      maxFileSize: 5 * 1024 * 1024,

      // 限制文件类型
      allowedFileTypes: ['image/*'],

      // 最多可上传几个文件
      maxNumberOfFiles: 10,

      // 跨域是否传递 cookie
      withCredentials: false,

      // 超时时间 30 秒
      timeout: 30 * 1000,
    },
    // 字体大小配置
    fontSize: {
      fontSizeList: [
        '12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px', '48px'
      ]
    },
    // 字体配置
    fontFamily: {
      fontFamilyList: [
        '宋体', '黑体', '楷体', '仿宋', '微软雅黑', 'Arial', 'Tahoma', 'Verdana', 'Times New Roman', 'Courier New'
      ]
    },
    // 颜色配置
    color: {
      colors: ['#000000', '#333333', '#666666', '#999999', '#cccccc', '#ffffff', '#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff']
    },
    bgColor: {
      colors: ['#000000', '#333333', '#666666', '#999999', '#cccccc', '#ffffff', '#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff']
    }
  },
  // 设置编辑器语言为中文
  i18nConf: {
    // 设置语言为中文
    lang: 'zh-CN',
    // 自定义中文配置
    langConf: {
      'zh-CN': {
        // 工具栏按钮文本
        toolbar: {
          bold: '粗体',
          italic: '斜体',
          underline: '下划线',
          strikeThrough: '删除线',
          fontSize: '字号',
          fontFamily: '字体',
          lineHeight: '行高',
          color: '文字颜色',
          bgColor: '背景色',
          indent: '增加缩进',
          delIndent: '减少缩进',
          justifyLeft: '左对齐',
          justifyRight: '右对齐',
          justifyCenter: '居中对齐',
          justifyJustify: '两端对齐',
          insertLink: '插入链接',
          unLink: '取消链接',
          bulletedList: '无序列表',
          numberedList: '有序列表',
          insertTable: '插入表格',
          codeBlock: '代码块',
          quote: '引用',
          divider: '分割线',
          undo: '撤销',
          redo: '重做',
          fullScreen: '全屏',
          todo: '待办事项'
        },
        // 菜单文本
        menus: {
          dropPanelMenu: {
            bold: '粗体',
            italic: '斜体',
            underline: '下划线',
            strikeThrough: '删除线'
          }
        }
      }
    }
  },

  // 图片上传配置（需替换为实际接口）
  // uploadFileName: 'file',
  // uploadImgHooks: {
  //   before: (file: any) => {
  //     console.log('开始上传图片:', file);
  //     return true; // 允许上传
  //   },
  //   success: (file: any, result: any) => {
  //     return result.data.url; // 假设接口返回 { data: { url: '图片地址' } }
  //   },
  //   error: (file: any, err: any) => {
  //     console.error('图片上传失败:', err);
  //     return false;
  //   }
  // }
};

// 处理Slate相关错误的恢复函数
const recoverFromSlateError = async (editor: IDomEditor) => {
  try {
    // console.log('尝试从Slate错误中恢复...');
    const success = await handleSlateError(editor, { message: 'Slate error recovery' });
    if (!success) {
      // console.error('Slate错误恢复失败');
    }
  } catch (error) {
    // console.error('执行Slate错误恢复时出错:', error);
  }
};

// 修复编辑器高度的函数
// 注意：此函数依赖 wangeditor 的内部 DOM 结构，升级时需要验证选择器的有效性
const fixEditorHeight = () => {
  if (!editorRef.value || !props.height) return;

  // 延迟执行确保 DOM 已完全渲染
  setTimeout(() => {
    const editorContainer = editorRef.value?.getEditableContainer().parentElement?.parentElement;
    if (editorContainer) {
      const toolbar = editorContainer.querySelector('.w-e-toolbar') as HTMLElement;
      const textContainer = editorContainer.querySelector('.w-e-text-container') as HTMLElement;
      const scrollContainer = editorContainer.querySelector('.w-e-scroll') as HTMLElement;

      if (toolbar && textContainer && scrollContainer) {
        const containerHeight = typeof props.height === 'number' ? props.height : parseInt(props.height);
        const toolbarHeight = toolbar.offsetHeight;
        const contentHeight = containerHeight - toolbarHeight;

        // 设置文本容器高度
        textContainer.style.height = `${contentHeight}px`;
        textContainer.style.overflow = 'hidden';

        // 设置滚动容器
        scrollContainer.style.height = `${contentHeight}px`;
        scrollContainer.style.overflowY = 'auto';
        scrollContainer.style.overflowX = 'hidden';
      }
    }
  }, 100);
};

// 生命周期钩子：编辑器创建时
const handleCreated = (editor: IDomEditor) => {
  editorRef.value = editor;

  // 添加全局错误监听
  const originalConsoleError = console.error;
  console.error = function (...args) {
    const errorMessage = args.join(' ');
    if (errorMessage.includes('Cannot resolve a Slate node from DOM node') ||
      errorMessage.includes('Cannot find a descendant at path')) {
      // console.warn('检测到Slate错误，尝试恢复:', errorMessage);
      recoverFromSlateError(editor);
    }
    originalConsoleError.apply(console, args);
  };

  // 修复高度问题
  fixEditorHeight();

  // 由于现在使用toolbarKeys明确控制按钮显示，不需要手动移除按钮
  // 只需要在DOM渲染完成后再次修复高度
  setTimeout(() => {
    // 再次修复高度，确保所有元素都已渲染完成
    fixEditorHeight();
  }, 300); // 增加延迟确保DOM完全渲染
  showStatus.value = true;
};

// 内容变化时更新 HTML
const handleChange = (editor: IDomEditor) => {
  try {
    const html = editor.getHtml();
    valueHtml.value = html;
    // 如果内容为空，传递空字符串而不是默认的空标签
    emits('update:modelValue', cleanWangEditorContent(html));
  } catch (error) {
    // console.error('处理编辑器内容变化时出错:', error);

    // 检查是否为Slate错误
    if (isSlateError(error)) {
      // console.warn('检测到Slate错误，尝试恢复...');
      recoverFromSlateError(editor);
    } else {
      handleEditorError(error, '内容变化处理');
    }

    // 尝试恢复到安全状态
    try {
      valueHtml.value = '<p><br></p>';
      emits('update:modelValue', '');
    } catch (recoveryError) {
      // console.error('恢复编辑器状态失败:', recoveryError);
    }
  }
};

// 监听外部数据变化，确保编辑器内容同步且为字符串类型
watch(() => props.modelValue, async (newValue: any) => {
  const stringValue = String(newValue || '');
  // 为编辑器准备内容（空字符串转换为默认空标签）
  let editorValue = prepareWangEditorContent(stringValue);

  // 如果内容包含obs-key标记，转换为实际URL用于显示
  try {
    editorValue = await convertKeysToObsUrls(editorValue);
  } catch (error) {
    // console.error('转换图片key为URL失败:', error);
  }

  if (editorValue !== valueHtml.value) {
    valueHtml.value = editorValue;
    // 如果编辑器已创建，则同步内容
    if (editorRef.value) {
      try {
        // 使用安全的方式设置编辑器内容
        await safeSetEditorContent(editorRef.value, editorValue);
      } catch (error) {
        handleEditorError(error, '设置编辑器内容');
        // 如果仍然失败，尝试设置为空内容
        try {
          editorRef.value.clear();
        } catch (clearError) {
          // console.error('清空编辑器失败:', clearError);
        }
      }
    }
  }
});

// 聚焦/失焦处理
const handleFocus = () => {
};
const handleBlur = () => {
};

// 组件销毁时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor) {
    editor.destroy();
    editorRef.value = null;
  }
});

// 监听高度变化
watch(() => props.height, () => {
  fixEditorHeight();
}, { flush: 'post' });

onMounted(() => {
  // 设置编辑器语言为中文
  i18nChangeLanguage('zh-CN');
});
</script>

<style lang="less">
/* 引入编辑器基础样式（注意路径匹配项目结构） */
@import '@wangeditor/editor/dist/css/style.css';

/* 编辑器容器样式 */
.editor-content-wrapper {
  position: relative;
}

.editor-content-wrapper.scrollable .w-e-text-container {
  overflow-y: auto !important;
}


/* 隐藏不需要的图片编辑功能，但保留基本的图片和上传图片功能 */
.w-e-toolbar [data-menu-key="imageWidth30"],
.w-e-toolbar [data-menu-key="imageWidth50"],
.w-e-toolbar [data-menu-key="imageWidth100"],
.w-e-toolbar [data-menu-key="deleteImage"],
.w-e-toolbar [data-menu-key="editImage"],
.w-e-toolbar [data-menu-key="viewImageLink"],
.w-e-toolbar [data-menu-key="imageAlt"],
.w-e-toolbar [data-menu-key="imageLink"],
.w-e-toolbar [data-menu-key="imageSize"],
.w-e-toolbar [data-menu-key="imageStyle"],
.w-e-toolbar [data-menu-key="imagePosition"],
.w-e-toolbar [data-menu-key="imageMargin"],
.w-e-toolbar [data-menu-key="imageBorder"],
.w-e-toolbar [data-menu-key="imageShadow"],
.w-e-toolbar [data-menu-key="imageOpacity"],
.w-e-toolbar [data-menu-key="imageRotate"],
.w-e-toolbar [data-menu-key="imageCrop"] {
  display: none !important;
}
.editor-border-wrap {
  box-sizing: border-box;
  width: 100%;
  padding: 0;
  overflow: hidden;
  /* 防止内容溢出圆角 */
  background: #fff;
  border: 1px solid var(--el-border-color);
  border-radius: 6px;
}

.wang-editor-container {
  margin: 1px;
  /* 让内容缩进去，避免盖住边框 */
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
  /* 不固定默认min-height，交由 props.minHeight 控制 */
}

/* 固定高度时使用flex布局，自动让文本区填满剩余空间 */
.wang-editor-container.fixed-height {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.wang-editor-container.fixed-height .w-e-full-screen-container {
  height: 100% !important;
}

/* 工具栏固定高度 */
.wang-editor-container.fixed-height .w-e-toolbar {
  flex: 0 0 auto;
  height: auto;
  min-height: 40px;
}

/* 编辑器内容区域自适应剩余高度 */
.wang-editor-container.fixed-height .w-e-text-container {
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden !important;
  position: relative;
}

/* 禁用容器本身的滚动 */
.wang-editor-container.fixed-height .w-e-text-container::-webkit-scrollbar {
  display: none;
}

.wang-editor-container.fixed-height .w-e-text-container .w-e-scroll {
  position: absolute !important;
  top: 0 !important;
  left: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
  height: auto !important;
  overflow-y: auto !important;
  overflow-x: hidden !important;
  -webkit-overflow-scrolling: touch;
  padding: 0 !important;
}

.wang-editor-container.fixed-height .w-e-text-container .w-e-text {
  min-height: 100%;
  padding: 10px;
  margin: 0;
}

/* 默认情况下，保留最小高度，避免modal/hoverbar定位异常 */
.w-e-text-container {
  min-height: 350px !important;
}

/* 默认滚动容器高度与行为（非固定高度时） */
.w-e-text-container .w-e-scroll {
  height: auto !important;
  min-height: 350px !important;
  -webkit-overflow-scrolling: touch;
}

/* 确保编辑器内容区域的HTML标签保持默认样式 */
.w-e-text-container .w-e-scroll {
  font-family: inherit;
  line-height: 1.5;
}
/* 确保编辑器内容区域的HTML标签保持默认样式 */
.w-e-text-container {
  P {
    margin: 0 !important;
  }
}


/* 修复字体下拉菜单样式 */
.w-e-toolbar .w-e-drop-panel {
  z-index: 9999999 !important;
}

.w-e-modal {
  .babel-container {
    margin-bottom: 0;

    span {
      margin-bottom: 0;
    }
  }

  button {
    padding: 1px 10px;
    margin-top: 10px;
  }
}
</style>
